package de.timoh.standardchatplugin;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.event.player.PlayerChatEvent;
import org.bukkit.event.player.PlayerEvent;
import org.bukkit.event.player.PlayerListener;

/**
 * ChatPlayerListener verwaltet alle Spielerkommandos und führt diese aus, sollten
 * sie vorhanden sein.
 *
 * @version 0.1
 * @author Timo
 *
 */
public class ChatPlayerListener extends PlayerListener{
    private final StandardChatPlugin plugin;

    private final static int WHO_ADMIN = 0;
    private final static int WHO_MOD = 1;
    private final static int WHO_PLAYER = 2;
    private final static int WHO_STAMMSPIELER = 3;
    private final static int WHO_GAST = 4;
    private final static int WHO_ALL = 5;

    public ChatPlayerListener(StandardChatPlugin instance) {
        plugin = instance;
    }

    /**
     * Methode zum erfassen von Spielern, die den Server joinen.
     *
     * @param event
     */
    @Override
    public void onPlayerJoin(PlayerEvent event){
        Player connectedPlayer = event.getPlayer();
        PlayerEx pex;
        connectedPlayer.sendMessage("Willkommen "+connectedPlayer.getName()+"!");
        if(PlayerEx.isPlayerInMap(connectedPlayer.getName())){
            pex = PlayerEx.getPlayer(connectedPlayer.getName());
            pex.setDisplayName(connectedPlayer);
        }else{
            connectedPlayer.sendMessage("Dies ist dein erster Besuch auf diesem Server. Bitte lies die Regeln!");
            pex = new PlayerEx(connectedPlayer.getName());
            pex.setRank(PlayerEx.RANK_GAST,false);
        }
        pex.setDisplayName(connectedPlayer);
    }

    /**
     * Hier werden alle Spielereingaben erkannt und ggf. ausgeführt!
     *
     * @param event
     */
    @Override
    public void onPlayerCommandPreprocess(PlayerChatEvent event) {
 	   Player players = event.getPlayer();
 	   String[] message = event.getMessage().split(" ");
 	   try{
               if(message[0].equalsIgnoreCase("/hilfe") || message[0].equalsIgnoreCase("/help")){
                   sendHelp(players);
               }else if(message[0].equalsIgnoreCase("/who")){
                   if(message.length > 1){
                       if(message[1].equalsIgnoreCase("admin")){
                           sendWho(players,WHO_ADMIN);
                       }else if(message[1].equalsIgnoreCase("mod")){
                           sendWho(players,WHO_MOD);
                       }else if(message[1].equalsIgnoreCase("spieler")){
                           sendWho(players,WHO_PLAYER);
                       }else if(message[1].equalsIgnoreCase("stammspieler")){
                           sendWho(players,WHO_STAMMSPIELER);
                       }else if(message[1].equalsIgnoreCase("gast")){
                           sendWho(players,WHO_GAST);
                       }
                   }else{
                       sendWho(players,WHO_ALL);
                   }
               }else if(message[0].equalsIgnoreCase("/ban")){
                   if(message.length > 1){
                       banPlayer(players,message[1]);
                   }else{
                       players.sendMessage(ChatColor.DARK_RED+"Fehler: "+ChatColor.WHITE+" Falscher Syntax!");
                   }

               }else if(message[0].equalsIgnoreCase("/kick")){
                   if(message.length > 1){
                       kickPlayer(players,message[1]);
                   }else{
                       players.sendMessage(ChatColor.DARK_RED+"Fehler: "+ChatColor.WHITE+" Falscher Syntax!");
                   }

               }else if(message[0].equalsIgnoreCase("/time")){
                   if(message.length > 1){
                       setTime(players,message[1]);
                   }else{
                       players.sendMessage(ChatColor.DARK_RED+"Fehler: "+ChatColor.WHITE+" Falscher Syntax!");
                   }
               }else if(message[0].equalsIgnoreCase("/setRank")){
                   if(message.length > 1){
                       setRank(players,message[1],message[2]);
                   }else{
                       players.sendMessage(ChatColor.DARK_RED+"Fehler: "+ChatColor.WHITE+" Falscher Syntax!");
                   }
               }else if(message[0].equalsIgnoreCase("/setHome")){
                   if(message.length > 1){
                       players.sendMessage(ChatColor.DARK_RED+"Fehler: "+ChatColor.WHITE+" Falscher Syntax!");
                   }else{
                       setHome(players);
                   }
               }else if(message[0].equalsIgnoreCase("/home")){
                   if(message.length > 1){
                       players.sendMessage(ChatColor.DARK_RED+"Fehler: "+ChatColor.WHITE+" Falscher Syntax!");
                   }else{
                       home(players);
                   }
               }else if(message[0].equalsIgnoreCase("/tp")){
                   if(message.length > 1){
                       tpToPlayer(players,message[1]);
                   }else{
                       players.sendMessage(ChatColor.DARK_RED+"Fehler: "+ChatColor.WHITE+" Falscher Syntax!");
                   }
               }
        }catch(ArrayIndexOutOfBoundsException ex){
            players.sendMessage(ChatColor.DARK_RED+"Fehler: "+ChatColor.WHITE+" Falscher Syntax! (Eventuell falsche Anzahl an Argumenten)");
        }
    }

    /**
     * Diese Methode wird aufgerufen, wenn ein Spieler /who eingibt. Sie informiert
     * ihn über alle Spieler die z.Z. online sind.
     * @param p Spieler der /who eingegeben hat
     * @param type Art der informatio z.B. nur Admins o.ä.
     */

    private void sendWho(Player p,int type){
        Player[] onlinePlayers = plugin.getServer().getOnlinePlayers();
        int length = onlinePlayers.length;
        int pCount = 0;
        String msg = "", pGroup = "";
        if (type == WHO_ADMIN) {
            for (int i = 0; i < length; i++) {
                if (PlayerEx.getPlayer(onlinePlayers[i].getName()).getRank() == PlayerEx.RANK_ADMIN) {
                    msg = msg + ChatColor.GOLD + onlinePlayers[i].getName() + ChatColor.WHITE+ " | ";
                }
                pCount++;
            }
            pGroup = "Anzuzeigende Spielergruppe: Admin";
        }else if(type == WHO_MOD){
            for (int i = 0; i < length; i++) {
                if (PlayerEx.getPlayer(onlinePlayers[i].getName()).getRank() == PlayerEx.RANK_MOD) {
                    msg = msg + ChatColor.AQUA + onlinePlayers[i].getName() + ChatColor.WHITE+ " | ";
                }
                pCount++;
            }
            pGroup = "Anzuzeigende Spielergruppe: Mod";
        }else if(type == WHO_PLAYER){
            for (int i = 0; i < length; i++) {
                if (PlayerEx.getPlayer(onlinePlayers[i].getName()).getRank() == PlayerEx.RANK_SPIELER) {
                    msg = msg + ChatColor.WHITE + onlinePlayers[i].getName() + " | ";
                }
                pCount++;
            }
            pGroup = "Anzuzeigende Spielergruppe: Spieler";
        }else if(type == WHO_STAMMSPIELER){
            for (int i = 0; i < length; i++) {
                if (PlayerEx.getPlayer(onlinePlayers[i].getName()).getRank() == PlayerEx.RANK_STAMMSPIELER) {
                    msg = msg + ChatColor.LIGHT_PURPLE + onlinePlayers[i].getName() + ChatColor.WHITE+ " | ";
                }
                pCount++;
            }
            pGroup = "Anzuzeigende Spielergruppe: Stammspieler";
        }else if(type == WHO_GAST){
            for (int i = 0; i < length; i++) {
                if (PlayerEx.getPlayer(onlinePlayers[i].getName()).getRank() == PlayerEx.RANK_GAST) {
                    msg = msg + ChatColor.GRAY + onlinePlayers[i].getName() + ChatColor.WHITE+ " | ";
                }
                pCount++;
            }
            pGroup = "Anzuzeigende Spielergruppe: Stammspieler";
        }else if(type == WHO_ALL){
            for (int i = 0; i < length; i++) {
                if (PlayerEx.getPlayer(onlinePlayers[i].getName()).getRank() == PlayerEx.RANK_ADMIN) {
                    msg = msg + ChatColor.GOLD + onlinePlayers[i].getName() + ChatColor.WHITE+ " | ";
                }else if (PlayerEx.getPlayer(onlinePlayers[i].getName()).getRank() == PlayerEx.RANK_MOD) {
                    msg = msg + ChatColor.AQUA + onlinePlayers[i].getName() + ChatColor.WHITE+ " | ";
                }else if (PlayerEx.getPlayer(onlinePlayers[i].getName()).getRank() == PlayerEx.RANK_SPIELER) {
                    msg = msg + ChatColor.WHITE + onlinePlayers[i].getName() + " | ";
                }else if (PlayerEx.getPlayer(onlinePlayers[i].getName()).getRank() == PlayerEx.RANK_STAMMSPIELER) {
                    msg = msg + ChatColor.LIGHT_PURPLE + onlinePlayers[i].getName() + ChatColor.WHITE+ " | ";
                }else if (PlayerEx.getPlayer(onlinePlayers[i].getName()).getRank() == PlayerEx.RANK_GAST) {
                    msg = msg + ChatColor.GRAY + onlinePlayers[i].getName() + ChatColor.WHITE+ " | ";
                }
                pCount++;
            }
            pGroup = "Anzuzeigende Spielergruppe: Alle";
        }
        p.sendMessage("Spieler online: "+pCount);
        p.sendMessage(pGroup);
        p.sendMessage(msg);
    }

    /**
     * Gibt dem Spieler alle zur Verfügung stehenden Eingaben bekannt.
     *
     * @param p
     */

    private void sendHelp(Player p){
        PlayerEx pex = PlayerEx.getPlayer(p.getName());
        int rank = pex.getRank();
        p.sendMessage(ChatColor.RED + "----- Eingaben die du verwenden kannst: -----");
        p.sendMessage("/help oder /hilfe");
        p.sendMessage("/who <Optional: admin/mod/stammspieler/spieler/gast>");
        //p.sendMessage("/warp <Warppunkt>");
        if(rank == PlayerEx.RANK_ADMIN){
            p.sendMessage("/kick <Spieler>");
            p.sendMessage("/ban <Spieler>");
            p.sendMessage("/time <Zeit: 0 - 24000>");
            p.sendMessage("/setRank <Spieler> <Rang: admin/mod/stammspieler/spieler/gast>");
            p.sendMessage("/tp <Spieler>");
            p.sendMessage("/setHome");
            p.sendMessage("/home");
        } else if (rank == PlayerEx.RANK_MOD) {
            p.sendMessage("/kick <Spieler>");
            p.sendMessage("/time <Zeit: 0 - 24000>");
            p.sendMessage("/setRank <Spieler> <Rang: admin/mod/stammspieler/spieler/gast>");
            p.sendMessage("/tp <Spieler>");
            p.sendMessage("/setHome");
            p.sendMessage("/home");
        } else if (rank == PlayerEx.RANK_STAMMSPIELER) {
            p.sendMessage("/setHome");
            p.sendMessage("/home");
        } else if (rank == PlayerEx.RANK_SPIELER) {
            p.sendMessage("/setHome");
            p.sendMessage("/home");
        }
    }

    /**
     * Diese Methode kickt einen Spieler vom Server.
     *
     * @param mod Der Admin/Mod der die Eingabe betätigt hat.
     * @param name Der zukickende Spieler
     */

    private void kickPlayer(Player mod, String name){
        if(PlayerEx.getPlayer(mod.getName()).getRank() == PlayerEx.RANK_ADMIN || PlayerEx.getPlayer(mod.getName()).getRank() == PlayerEx.RANK_MOD ){
            Player p;
            if(plugin.isPlayerOnline(name)){
                p = plugin.getServer().getPlayer(name);
                p.kickPlayer("Du wurdest gekickt!");
                plugin.getServer().broadcastMessage(name+" wurde vom Server gegickt!");
            }else{
                mod.sendMessage(ChatColor.DARK_RED+"Fehler: "+ChatColor.WHITE+" Der Spieler wurde nicht gefunden.");
            }
        }else{
            mod.sendMessage(ChatColor.DARK_RED+"Fehler: "+ChatColor.WHITE+" Du hast nicht die Rechte um diesen Ausdruck zu nutzen.");
        }
    }

    /**
     * Bannt einen Spieler vom Server. Ruft dazu banPlayerSave(path,Spieler) auf, um
     * den Spieler in die banned-players Datei einzutragen.
     *
     * @param mod
     * @param name
     */

    private void banPlayer(Player mod, String name){
        if(PlayerEx.getPlayer(mod.getName()).getRank() == PlayerEx.RANK_ADMIN){
            Player p;
            if(PlayerEx.isPlayerInMap(name)){
                if(plugin.isPlayerOnline(name)){
                    p = plugin.getServer().getPlayer(name);
                    p.kickPlayer("Du wurdest vom Server gebannt!");
                    banPlayerSave("banned-players.txt",name);
                    plugin.getServer().broadcastMessage(ChatColor.DARK_GREEN+"Server: "+ChatColor.DARK_RED+name+ChatColor.WHITE+" wurde vom Server gebannt!");
                }
            }else{
                mod.sendMessage(ChatColor.DARK_RED+"Fehler: "+ChatColor.WHITE+" Der Spieler wurde nicht gefunden.");
            }
        }else{
            mod.sendMessage(ChatColor.DARK_RED+"Fehler: "+ChatColor.WHITE+" Du hast nicht die Rechte um diesen Ausdruck zu nutzen.");
        }
    }

    /**
     * Methode zum Speichern von gebannten Spielern.
     *
     * @param path
     * @param name
     */

    private void banPlayerSave(String path, String name){
        try {
            BufferedWriter bw = new BufferedWriter(new FileWriter(path, true));
            bw.write(name);
            bw.close();
        } catch (IOException ex) {
            System.err.println("Fehler: "+ex);
        }
    }

    /**
     * Diese Methode setzt die Zeit des Servers. Wird in zukünftiger Version durch
     * einen boolean-Wert erweitert, um einen Timefreeze zu ermöglichen!
     *
     * @param mod
     * @param time
     */

    private void setTime(Player mod, String time){   
        if(PlayerEx.getPlayer(mod.getName()).getRank() == PlayerEx.RANK_ADMIN || PlayerEx.getPlayer(mod.getName()).getRank() == PlayerEx.RANK_MOD ){
            try{
                long t = Long.parseLong(time);
                plugin.getServer().getWorld("world").setTime(t);
                mod.sendMessage(ChatColor.DARK_GREEN+"Server: "+ChatColor.WHITE+" Zeit wurde geändert zu "+t);
            }catch(NumberFormatException ex){
                mod.sendMessage(ChatColor.DARK_RED+"Fehler: "+ChatColor.WHITE+" Der Angegebene Parametar ist kein Zahlenwert!");
            }
        }else{
            mod.sendMessage(ChatColor.DARK_RED+"Fehler: "+ChatColor.WHITE+" Du hast nicht die Rechte um diesen Ausdruck zu nutzen.");
        }
    }

    /**
     * Speichert die Koordianten des Spielers als Home in PlayerEx
     * 
     * @param player
     */

    private void setHome(Player player){
        if(PlayerEx.getPlayer(player.getName()).getRank() != PlayerEx.RANK_GAST){
            PlayerEx pex = PlayerEx.getPlayer(player.getName());
            Location loc = player.getLocation();
            pex.setHome(loc);
            player.sendMessage(ChatColor.YELLOW+"Home wurde erfolgreich gesetzt!");
        }
    }

    /**
     * Teleportiert den Spieler zu seinem vorher gesetzten Home.
     *
     * @param player
     */

    private void home(Player player){
        if(PlayerEx.getPlayer(player.getName()).getRank() != PlayerEx.RANK_GAST){
            PlayerEx pex = PlayerEx.getPlayer(player.getName());
            if(pex.isHomeSet()){
                Location loc = pex.getHome(player);
                player.teleportTo(loc);
                player.sendMessage("Willkommen zuhause!");
            }else{
                player.sendMessage(ChatColor.DARK_RED+"Fehler: "+ChatColor.WHITE+" Home ist noch nicht gesetzt!");
            }
        }else{
            player.sendMessage(ChatColor.DARK_RED+"Fehler: "+ChatColor.WHITE+" Du hast nicht die Rechte um diesen Ausdruck zu nutzen.");
        }
    }

    /**
     * Teleportiert den Admin oder Mod zu dem angegebenen Spieler.
     *
     * @param mod
     * @param name
     */

    private void tpToPlayer(Player mod, String name){
        if(PlayerEx.getPlayer(mod.getName()).getRank() == PlayerEx.RANK_ADMIN || PlayerEx.getPlayer(mod.getName()).getRank() == PlayerEx.RANK_MOD){
            if(plugin.isPlayerOnline(name)){
                Player player = plugin.getServer().getPlayer(name);
                mod.teleportTo(player);
            }else{
                mod.sendMessage(ChatColor.DARK_RED+"Fehler: "+ChatColor.WHITE+" Der Spieler wurde nicht gefunden!");
            }
        }else{
            mod.sendMessage(ChatColor.DARK_RED+"Fehler: "+ChatColor.WHITE+" Du hast nicht die Rechte um diesen Ausdruck zu nutzen.");
        }
    }

    /**
     * Ermöglicht einen Admin den Rang eines anderen nicht Admins zu verändern.
     *
     * @param mod
     * @param name
     * @param rank
     */

    private void setRank(Player mod, String name, String rank){
        if(PlayerEx.getPlayer(mod.getName()).getRank() == PlayerEx.RANK_ADMIN){
            if(PlayerEx.isPlayerInMap(name)){
                PlayerEx pex = PlayerEx.getPlayer(name);
                int rankI = stringToRank(rank);
                if(rankI != -1){
                    pex.setRank(rankI,true);
                    if(plugin.isPlayerOnline(name)){
                        Player p = plugin.getServer().getPlayer(name);
                        pex.setDisplayName(p);
                        plugin.getServer().broadcastMessage(ChatColor.RED+name+ " ist nun "+rank.toUpperCase());
                    }
                    PlayerHandler.save();
                }else{
                    mod.sendMessage(ChatColor.DARK_RED+"Fehler: "+ChatColor.WHITE+" Dieser Rang existiert nicht!");
                }
            }else{
                mod.sendMessage(ChatColor.DARK_RED+"Fehler: "+ChatColor.WHITE+" Der Spieler wurde nicht gefunden!");
            }
        }else{
            mod.sendMessage(ChatColor.DARK_RED+"Fehler: "+ChatColor.WHITE+" Du hast nicht die Rechte um diesen Ausdruck zu nutzen.");
        }
    }

    /**
     * Einfache Methode zum Umwandeln von Stringeingaben in Spielerränge.
     *
     * @param rank
     * @return
     */

    private int stringToRank(String rank){
        if(rank.equals("admin")){
            return PlayerEx.RANK_ADMIN;
        }else if(rank.equals("mod")){
            return PlayerEx.RANK_MOD;
        }else if(rank.equals("stammspieler")){
            return PlayerEx.RANK_STAMMSPIELER;
        }else if(rank.equals("spieler")){
            return PlayerEx.RANK_SPIELER;
        }else if(rank.equals("gast")){
            return PlayerEx.RANK_GAST;
        }
        return -1;
    }

}
